package com.linln.admin.app.service.task;

import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.linln.admin.app.constants.AppConstants;
import com.linln.admin.app.constants.TaskTypeEnum;
import com.linln.admin.app.domain.AppInfo;
import com.linln.admin.app.domain.AppVersion;
import com.linln.admin.app.domain.RepoAccount;
import com.linln.admin.app.domain.VersionApp;
import com.linln.admin.app.service.branch.BranchHelper;
import com.linln.admin.system.domain.TaskQueue;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.List;
import java.util.Optional;

/**
 * 将开发分支合并到release上
 */
@Service
@Slf4j
public class MergeDev2ReleaseTask extends AbstractTaskExecutor {
    /**
     * 是否可以处理这个任务
     *
     * @param t
     * @return
     */
    @Override
    public boolean support(TaskQueue t) {
        return t != null && TaskTypeEnum.MERGE_DEV_RELEASE.getType().equals(t.getType());
    }

    /**
     * 处理任务，并返回处理结果
     *
     * @param t
     * @return true-成功; 其它-false
     */
    @Override
    public boolean exec(TaskQueue t) {
        String json = t.getData();
        if (StringUtils.isBlank(json)) {
            log.warn("将dev分支合并到release分支任务没有data数据");
            return true;
        }

        try {
            Long versionId = t.getRelate_id();
            Optional<AppVersion> ver = versionRepository.findById(versionId);
            if (!ver.isPresent()) {
                throw new IllegalArgumentException("对应的版本信息不存在！");
            }
            AppVersion version = ver.get();
            if (AppConstants.YES.equals(version.getHotfix_flag())) {
                return false;//紧急修复版本不需要切release分支
            }
            List<String> recIds = new ObjectMapper().readValue(json, new TypeReference<List<String>>() {
            });
            for (String rid : recIds) {
                if (StringUtils.isBlank(rid) || (!StringUtils.isNumeric(rid))) {
                    log.warn("version_app表主键recId[" + rid + "]不存在！");
                    continue;
                }
                Long recId = Long.parseLong(rid);
                Optional<VersionApp> ova = versionAppRepository.findById(recId);
                if (!ova.isPresent()) {
                    log.warn("version_app表主键记录[" + rid + "]不存在！");
                    continue;
                }
                VersionApp va = ova.get();
                Optional<AppInfo> app = infoRepository.findById(va.getApp_id());
                if (!app.isPresent()) {
                    versionAppRepository.delete(va);
                    continue;
                }
                String baseVer = version.getVersion().trim().replace(" ", "");
                if (baseVer.startsWith(AppConstants.BRANCH_DEV_PREFIX)) {
                    baseVer = baseVer.substring(4);
                }
                va.setMerge_to_time(new Date());
                AppInfo info = app.get();
                try {
                    RepoAccount account = getRepoAccount(info.getRepo_account_id());
                    if (BranchHelper.findHandler(info.getRepo_type()).mergeBranch(baseVer, info.getRepo_url(), account.getAccount(), account.getPass(), AppConstants.BRANCH_DEV_PREFIX + baseVer, AppConstants.BRANCH_RELEASE_PREFIX + baseVer)) {
                        va.setMerge_to_status(AppConstants.VERSION_MERGE_STATUS_AUTO_MERGED);
                    } else {
                        va.setMerge_to_status(AppConstants.VERSION_MERGE_STATUS_CONFLICT);
                    }
                } catch (Exception e) {
                    log.error("dev->release失败[" + info.getDisplay_name() + "#" + version.getVersion() + "]：" + e.getMessage(), e);
                    va.setMerge_to_status(AppConstants.VERSION_MERGE_STATUS_NOMAL);
                }
                versionAppRepository.save(va);
            }
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            t.setMsg("task[" + t.getId() + "]执行失败！" + e);
            return false;
        }
        return true;
    }
}
